#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <string.h>

using namespace std;

#define LOG_PAth "diary/"

#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4

#define SCREEN 1
#define ONEFILE 2
#define CLASSIFYFILE 3

#define SIZE 1024

class Log
{
public:
    const char* level_to_string(int level)
    {
        switch(level)
        {
            case Info:
                return "INFO";
            case Debug:
                return "DEBUG";
            case Warning:
                return "WARNING";
            case Error:
                return "ERROR";
            case Fatal:
                return "FATAL"; 
        }
    }

    void record_onefile(const char* buffer)
    {
        char path[SIZE];
        snprintf(path,sizeof(path),"%s%s",LOG_PAth,"log");
        cout<<path<<endl;
        cout<<buffer<<endl;
        int fd = open(path,O_CREAT|O_WRONLY|O_TRUNC,0666);
        if(fd < 0)
        {
            perror("log file open fail");
            return;
        }

        write(fd,buffer,strlen(buffer));

        close(fd);
    }

    void record_classifyfile(int level,const char* buffer)
    {
        char path[SIZE];
        snprintf(path,sizeof(path),"%s%s%s",LOG_PAth,"log.",level_to_string(level));
        int fd = open(path,O_CREAT|O_WRONLY|O_TRUNC,0666);
        if(fd < 0)
        {
            perror("log file open fail");
            return;
        }

        write(fd,buffer,strlen(buffer));

        close(fd);
    }

    void record_log(int record,int level,const char* buffer)
    {
        switch(record)
        {
            case SCREEN:
                cout<<buffer<<endl;
                break;
            case ONEFILE:
                record_onefile(buffer);
                break;
            case CLASSIFYFILE:
                record_classifyfile(level,buffer);
                break;
        }
    }

    void operator()(int level,const char* format,...)
    {
        va_list s;
        va_start(s,format);
        char rightbuffer[SIZE];
        vsnprintf(rightbuffer,sizeof(rightbuffer),format,s);
        va_end(s);

        char leftbuffer[SIZE];
        time_t t=time(NULL);
        struct tm* mytime=localtime(&t);
        snprintf(leftbuffer,sizeof(leftbuffer),"[%s][%d-%d-%d %d:%d:%d]",level_to_string(level),1900+(mytime->tm_year),
        mytime->tm_mon,mytime->tm_mday,mytime->tm_hour,mytime->tm_min,mytime->tm_sec);

        char buffer[2*SIZE];
        snprintf(buffer,sizeof(buffer),"%s %s",leftbuffer,rightbuffer);

        //cout<<buffer<<endl;
        record_log(record,level,buffer);
    }

public:
    int record = SCREEN;
};


Log lg;
